﻿using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;
using System.IO;

namespace ClojureBox
{
    public partial class frmACB : Form
    {
        private const string STR_ACBini = "ACB.ini";

        private bool _mouseDown;
        private Point _mouseLoc;
        private Point _formPosition;
        private bool _needToSave;

        private AppConf _defaultApp;
        AppConf _sciteApp;
        AppConf _wincmdApp;

        String _jdkPath;

        private enum MenuHeader
        {
            None,
            JDKPath,
            Setup
        }

        public frmACB()
        {
            InitializeComponent();

            System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath();
            gp.AddRectangle(new Rectangle(10, 0, this.Width-12, this.Height));

            this.Region = new Region(gp);

            string cljBoxPath = AppDomain.CurrentDomain.BaseDirectory;

            _sciteApp = new AppConf(String.Format("Scite,{0}bin\\scite\\scite.exe,False,-1,-1", cljBoxPath));
            _wincmdApp = new AppConf(String.Format("WinCommand,{0}bin\\wincommand\\WinCommand.exe,False,-1,-1", cljBoxPath));

            cm.Items.Clear();
            ToolStripMenuItem sciteMI = new ToolStripMenuItem(_sciteApp.Name, Properties.Resources.scite, new EventHandler(Execute));
            cm.Items.Add(sciteMI);

            ToolStripMenuItem winCmdMI = new ToolStripMenuItem(_wincmdApp.Name, Properties.Resources.wc, new EventHandler(Execute));
            cm.Items.Add(winCmdMI);

            cm.Items.Add("-");
            cm.Items.Add("Explore Box", null, new EventHandler(ExploreHere));
            cm.Items.Add("Select JDK Path", null, new EventHandler(SelectJDKPath));
            cm.Items.Add("-");
            cm.Items.Add("Exit", null, new EventHandler(Exit));
        }

        #region INI Area

        private void LoadINIFile()
        {
            StreamReader sr = File.OpenText(STR_ACBini);
            String line = sr.ReadLine();
            MenuHeader mh = MenuHeader.None;
            while (line != null)
            {
                switch (line)
                {
                    case "[JDKPath]":
                        mh = MenuHeader.JDKPath;
                        break;
                    case "[Setup]":
                        mh = MenuHeader.Setup;
                        break;
                    case "":
                        break;
                    default:

                        switch (mh)
                        {
                            case MenuHeader.JDKPath:
                                _jdkPath = line;
                                break;

                            case MenuHeader.Setup:
                                this.Location = new Point(Convert.ToInt32(line.Substring(0, line.IndexOf(","))), Convert.ToInt32(line.Substring(line.IndexOf(",") + 1)));
                                _defaultApp = GetAppConfObjectFromAppName(sr.ReadLine());
                                break;
                        }
                        break;
                }
                line = sr.ReadLine();
            }
            sr.Close();
            _needToSave = false;
        }

        private void SaveINIFile()
        {
            if (_needToSave)
            {
                StreamWriter sw = new StreamWriter(STR_ACBini, false);
                sw.WriteLine("[JDKPath]");
                sw.WriteLine(_jdkPath);
                sw.WriteLine(string.Empty);

                sw.WriteLine("[Setup]");
                sw.WriteLine(this.Location.X + "," + this.Location.Y);
                sw.WriteLine(_defaultApp.Name);

                sw.Close();
            }
        }

        #endregion

        #region Helpers

        private void ExecuteApp(AppConf app, string args)
        {
            ProcessStartInfo pInfo = new ProcessStartInfo(app.Path, args);

            pInfo.CreateNoWindow = true;
            pInfo.UseShellExecute = app.NeedShell;
            if (app.X >= 0 || app.Y >= 0)
            {
                pInfo.Arguments = app.X + "," + app.Y;
            }
            pInfo.WorkingDirectory = Path.GetDirectoryName(app.Path);

            Process.Start(pInfo);
        }

        private void DrawBorder()
        {
            System.Drawing.Graphics a = this.CreateGraphics();
            a.DrawRectangle(new Pen(Color.Gray, 2), 10, 0, this.Width - 20, this.Height);
        }

        private AppConf GetAppConfObjectFromAppName(string appName)
        {
            if (appName.Equals(_sciteApp.Name))
            {
                return _sciteApp;
            }
            else
            {
                return _wincmdApp;
            }
        }

        #endregion

        private void frmACB_Load(object sender, EventArgs e)
        {
            LoadINIFile();
        }

        private void frmACB_FormClosing(object sender, FormClosingEventArgs e)
        {
            SaveINIFile();
        }

        private void Execute(Object sender, System.EventArgs e)
        {
            string appName = ((ToolStripMenuItem)sender).Text;

            _needToSave = true;

            ExecuteApp(GetAppConfObjectFromAppName(appName), string.Empty);
        }

        private void SelectJDKPath(Object sender, System.EventArgs e)
        {
            Config cfg = new Config();
            cfg.JDKPath = _jdkPath;
            cfg.ShowDialog();

            _jdkPath = cfg.JDKPath;
            _needToSave = true;
        }

        private void ExploreHere(Object sender, System.EventArgs e)
        {
            Process.Start("explorer", ".");
        }

        private void Exit(Object sender, System.EventArgs e)
        {
            this.Close();
        }

        private void frmACB_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                string[] paths = (string[])e.Data.GetData(DataFormats.FileDrop);
                string args = string.Concat(paths);

                ExecuteApp(_sciteApp, args);
            }
        }

        private void frmACB_DragEnter(object sender, DragEventArgs e)
        {
            DrawBorder();
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Link;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void frmACB_MouseDown(object sender, MouseEventArgs e)
        {
            DrawBorder();
            _mouseDown = true;
            _mouseLoc = new Point(e.X, e.Y);
            _formPosition = this.Location;
        }

        private void frmACB_MouseUp(object sender, MouseEventArgs e)
        {
            _mouseDown = false;
            if (e.Button == MouseButtons.Right)
            {
                cm.Show(this, new Point(_mouseLoc.X, _mouseLoc.Y));
            }
            else if (e.Button == MouseButtons.Left && _formPosition == this.Location)
            {
                ExecuteApp(_defaultApp, string.Empty);
            }
        }

        private void frmACB_MouseMove(object sender, MouseEventArgs e)
        {
            if (_mouseDown)
            {
                DrawBorder();
                this.Location = new Point(this.Left + e.X - _mouseLoc.X, this.Top + e.Y - _mouseLoc.Y);
                _needToSave = true;
            }
        }

        private void frmACB_MouseEnter(object sender, EventArgs e)
        {
            DrawBorder();
        }

        private void frmACB_MouseLeave(object sender, EventArgs e)
        {
            this.Refresh();
        }
    }

    public struct AppConf
    {
        public string Name;
        public string Path;
        public bool NeedShell;
        public int X;
        public int Y;

        public AppConf(string line)
        {
            string[] conf = line.Split(',');
            Name = conf[0];
            Path = conf[1];
            NeedShell = Convert.ToBoolean(conf[2]);
            X = int.Parse(conf[3]);
            Y = int.Parse(conf[4]);
        }

        public override string ToString()
        {
            return Name + "," + Path + "," + NeedShell.ToString() + "," + X.ToString() + "," + Y.ToString();
        }

        public override bool Equals(object obj)
        {
            return ((AppConf)obj).Name.Equals(this.Name);
        }
    }
}
